#include <stdio.h>
#include <stdlib.h>


/**************************************************************
This file contains the custom memory allocator code. This is
used to allocate small chunks of memory a few bytes in size.
On most systems, the memory page size is expected to be 4KB.
I sincerely hope that allocating memory in blocks that are
multiples of memory pages will help avoid memory fragmentation.
**************************************************************/


//about 16MiB
#define PAGE_SIZE 4096
#define CUSTOM_MALLOC_BUFSIZE ( PAGE_SIZE * 4096 ) - sizeof( void* ) - sizeof( size_t )

struct memory_buf{
	char               buf[CUSTOM_MALLOC_BUFSIZE];
	size_t             used;
	struct memory_buf* next;
};

//cma means Custom Memory Allocation
static struct memory_buf* g_cma_root;
static struct memory_buf* g_cma_memory;

int customMallocInit( void ){
	
	g_cma_root = malloc( sizeof(struct memory_buf) );
	if( !g_cma_root ){
		printf( "%s: Memory allocation failed.\n", __FUNCTION__ );
		return -1;
	}
	
	g_cma_root->next = NULL;
	g_cma_memory = g_cma_root;
	g_cma_memory->used = 0;
	
	return 0;
}

void* customMalloc( size_t count ){
	
	void* p;
	
	if( count > CUSTOM_MALLOC_BUFSIZE - g_cma_memory->used ){
		
		if( count > CUSTOM_MALLOC_BUFSIZE ) return NULL;
		
		g_cma_memory->next = malloc( sizeof(struct memory_buf) );
		if( !g_cma_memory->next ){
			printf( "%s: Memory allocation failed.\n", __FUNCTION__ );
			return NULL;
		}
		g_cma_memory = g_cma_memory->next;
		g_cma_memory->next = NULL;
		g_cma_memory->used = 0;
	}
	
	p = g_cma_memory->buf + g_cma_memory->used;
	g_cma_memory->used += count;
	
	return p;
}

void customFreeAll( void ){
	
	struct memory_buf* next;
	
	while( g_cma_root ){
		next = g_cma_root->next;
		free( g_cma_root );
		g_cma_root = next;
	}
}
